﻿using System;
using System.Linq;
using System.Security.Cryptography;

namespace CryptoQrUtilities.Cryption
{
    /// <summary>
    /// Provides a lazy initialized RSA service based on given RSA parameters.
    /// </summary>
    public class ImportedRsaProvider : IRsaProvider
    {
        private readonly RSAParameters m_parameters;

        /// <summary>
        /// Create a new instance of <see cref="ImportedRsaProvider"/> initializing by given RSA parameters.
        /// </summary>
        /// <param name="parameters">The parameters to use.</param>
        /// <param name="useOaepPadding">Whether to use OAEP padding when encryptin/decrypting.</param>
        public ImportedRsaProvider(RSAParameters parameters, bool useOaepPadding = true)
        {
            m_parameters = parameters;
            UseOaepPadding = useOaepPadding;
        }

        #region IRsaProvider implementation

        public RSACryptoServiceProvider GetRsaProvider()
        {
            var rsaService = new RSACryptoServiceProvider();

            rsaService.ImportParameters(m_parameters);
            return rsaService;
        }

        /// <summary>
        /// Gets whether to use OAEP padding.
        /// </summary>
        public bool UseOaepPadding { get; private set; }

        #endregion

        #region IEquatable implementation

        public bool Equals(IRsaProvider other)
        {
            var importedOther = other as ImportedRsaProvider;

            if (importedOther != null)
            {
                return
                    m_parameters.Exponent.SequenceEqual(importedOther.m_parameters.Exponent) &&
                    m_parameters.Modulus.SequenceEqual(importedOther.m_parameters.Modulus);
            }

            return Equals(this, other);
        }

        #endregion

        #region Object overrides

        public override int GetHashCode()
        {
            return m_parameters.Exponent.GetHashCode() ^ m_parameters.Modulus.GetHashCode();
        }

        #endregion
    }
}
